Python para Desenvolvedores

2ª edição, revisada e ampliada

Capítulo 26: Threads


Uma thread é uma linha de execução que compartilha sua área de memória com outras linhas, ao contrário do processo tradicional, que possui apenas uma linha com área de memória própria.

O uso de threads oferece algumas vantagens em relação aos processos convencionais:

  • Consomem menos recursos de máquina.
  • Podem ser criadas e destruídas mais rapidamente.
  • Podem ser chaveadas mais rapidamente.
  • Podem se comunicar com outras threads de forma mais fácil.

É comum utilizar threads para:

  • Processamento paralelo, em casos como atender várias conexões em processos servidores.
  • Executar operações de I/O assíncronas, por exemplo: enquanto o usuário continua interagindo com a interface enquanto a aplicação envia um documento para a impressora.
  • Operações de I/O em paralelo.

Em Python, o módulo da biblioteca padrão threading provê classes de alto nível de abstração e usa o módulo thread, que implementa as rotinas de baixo nível e geralmente não é usado diretamente.

Exemplo com o módulo threading:


In [1]:
"""
Exemplo de uso de threads
"""

import os
import time
import threading


class Monitor(threading.Thread):
    """
    Classe de monitoramento usando threads
    """
    def __init__(self, ip):
        """
        Construtor da thread
        """
        # Atributos para a thread
        self.ip = ip
        self.status = None

        # Inicializador da classe Thread
        threading.Thread.__init__(self)

    def run(self):
        """
        Código que será executado pela thread
        """
        # Execute o ping
        ping = os.popen('ping -n 1 %s' % self.ip).read()

        if 'Esgotado' in ping:
            self.status = False
        else:
            self.status = True


if __name__ == '__main__':

    # Crie uma lista com um objeto de thread para cada IP
    monitores = []
    for i in range(1, 11):

        ip = '10.10.10.%d' % i
        monitores.append(Monitor(ip))

    # Execute as Threads
    for monitor in monitores:
        monitor.start()

    # A thread principal continua enquanto
    # as outras threads executam o ping
    # para os endereços da lista

    # Verifique a cada segundo
    # se as threads acabaram
    ping = True

    while ping:
        ping = False

        for monitor in monitores:
            if monitor.status == None:
                ping = True
                break
            
        time.sleep(1)

    # Imprima os resultados no final
    for monitor in monitores:

        if monitor.status:
            print '%s no ar' % monitor.ip
        else:
            print '%s fora do ar' % monitor.ip


10.10.10.1 no ar
10.10.10.2 no ar
10.10.10.3 no ar
10.10.10.4 no ar
10.10.10.5 no ar
10.10.10.6 no ar
10.10.10.7 no ar
10.10.10.8 no ar
10.10.10.9 no ar
10.10.10.10 no ar

É importante observar que, quando o processo morre, todas as suas threads terminam.

Na versão 2.6, está disponível também o módulo multiprocessing, que implementa classes para a criação de processos e a comunicação entre eles.


In [1]:



Out[1]: